package com.cencat.user.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.HashSet;

/**
 * 用户角色关联更新DTO
 * @author cencat
 * @since 2024-01-01
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "用户角色关联更新DTO")
public class UserRoleUpdateDTO {

    /**
     * 关联ID
     */
    @NotNull(message = "关联ID不能为空")
    @Min(value = 1, message = "关联ID必须大于0")
    @Schema(description = "关联ID", example = "1")
    private Long id;

    /**
     * 用户ID
     */
    @Schema(description = "用户ID", example = "1")
    private Long userId;

    /**
     * 角色ID
     */
    @Schema(description = "角色ID", example = "1")
    private Long roleId;

    /**
     * 分配人ID
     */
    @Schema(description = "分配人ID", example = "1")
    private Long assignBy;

    /**
     * 分配人姓名
     */
    @Size(max = 50, message = "分配人姓名长度不能超过50个字符")
    @Schema(description = "分配人姓名", example = "管理员")
    private String assignByName;

    /**
     * 有效期开始时间
     */
    @Schema(description = "有效期开始时间", example = "2024-01-01T00:00:00")
    private LocalDateTime validFrom;

    /**
     * 有效期结束时间
     */
    @Schema(description = "有效期结束时间", example = "2024-12-31T23:59:59")
    private LocalDateTime validTo;

    /**
     * 状态（true-启用，false-禁用）
     */
    @Schema(description = "状态（true-启用，false-禁用）", example = "true")
    private Boolean status;

    /**
     * 备注
     */
    @Size(max = 500, message = "备注长度不能超过500个字符")
    @Schema(description = "备注", example = "系统管理员角色")
    private String remark;

    /**
     * 更新人ID
     */
    @Schema(description = "更新人ID", example = "1")
    private Long updateBy;

    /**
     * 版本号（乐观锁）
     */
    @Schema(description = "版本号", example = "1")
    private Integer version;

    /**
     * 有效期天数（用于快速设置有效期）
     */
    @Min(value = 1, message = "有效期天数必须大于0")
    @Max(value = 3650, message = "有效期天数不能超过3650天")
    @Schema(description = "有效期天数", example = "365")
    private Integer validDays;

    /**
     * 延长天数（用于延长有效期）
     */
    @Min(value = 1, message = "延长天数必须大于0")
    @Max(value = 365, message = "延长天数不能超过365天")
    @Schema(description = "延长天数", example = "30")
    private Integer extendDays;

    /**
     * 是否发送通知
     */
    @Schema(description = "是否发送通知", example = "true")
    private Boolean sendNotification = false;

    /**
     * 通知方式（email, sms, system）
     */
    @Schema(description = "通知方式", example = "email")
    private String notificationMethod;

    /**
     * 更新字段列表（用于部分更新）
     */
    @Schema(description = "更新字段列表")
    private Set<String> updateFields;

    /**
     * 批量更新的ID列表
     */
    @Schema(description = "批量更新的ID列表")
    private List<Long> ids;

    /**
     * 操作类型（enable, disable, extend, expire）
     */
    @Schema(description = "操作类型", example = "enable")
    private String operationType;

    /**
     * 是否强制更新（忽略版本检查）
     */
    @Schema(description = "是否强制更新", example = "false")
    private Boolean forceUpdate = false;

    // 构造函数
    public UserRoleUpdateDTO(Long id) {
        this.id = id;
        this.updateFields = new HashSet<>();
        this.sendNotification = false;
        this.forceUpdate = false;
    }

    public UserRoleUpdateDTO(Long id, Integer version) {
        this(id);
        this.version = version;
    }

    public UserRoleUpdateDTO(List<Long> ids, String operationType) {
        this.ids = ids;
        this.operationType = operationType;
        this.updateFields = new HashSet<>();
        this.sendNotification = false;
        this.forceUpdate = false;
    }

    // 业务方法

    /**
     * 校验有效期设置
     * @return 校验结果
     */
    public boolean isValidPeriodValid() {
        if (validFrom == null && validTo == null) {
            return true; // 无限期有效
        }
        
        if (validFrom != null && validTo != null) {
            return validFrom.isBefore(validTo);
        }
        
        return true;
    }

    /**
     * 校验操作类型
     * @return 校验结果
     */
    public boolean isOperationTypeValid() {
        if (operationType == null || operationType.trim().isEmpty()) {
            return true;
        }
        
        String type = operationType.toLowerCase();
        return "enable".equals(type) || "disable".equals(type) || 
               "extend".equals(type) || "expire".equals(type) ||
               "refresh".equals(type) || "reset".equals(type);
    }

    /**
     * 添加更新字段
     * @param field 字段名
     */
    public void addUpdateField(String field) {
        if (updateFields == null) {
            updateFields = new HashSet<>();
        }
        updateFields.add(field);
    }

    /**
     * 检查是否需要更新指定字段
     * @param field 字段名
     * @return 是否需要更新
     */
    public boolean shouldUpdateField(String field) {
        return updateFields == null || updateFields.isEmpty() || updateFields.contains(field);
    }

    /**
     * 获取实际的有效期结束时间
     * @return 有效期结束时间
     */
    public LocalDateTime getActualValidTo() {
        if (validDays != null && validDays > 0) {
            LocalDateTime startTime = validFrom != null ? validFrom : LocalDateTime.now();
            return startTime.plusDays(validDays);
        }
        return validTo;
    }

    /**
     * 检查是否需要发送通知
     * @return 是否需要发送通知
     */
    public boolean shouldSendNotification() {
        return sendNotification != null && sendNotification && 
               notificationMethod != null && !notificationMethod.trim().isEmpty();
    }

    /**
     * 检查是否为批量更新
     * @return 是否为批量更新
     */
    public boolean isBatchUpdate() {
        return ids != null && ids.size() > 1;
    }

    /**
     * 获取所有需要更新的ID
     * @return ID列表
     */
    public List<Long> getAllUpdateIds() {
        if (ids != null && !ids.isEmpty()) {
            return ids;
        }
        if (id != null) {
            return List.of(id);
        }
        return List.of();
    }

    /**
     * 设置状态更新
     * @param status 状态
     */
    public void setStatusUpdate(Boolean status) {
        this.status = status;
        addUpdateField("status");
    }

    /**
     * 设置有效期更新
     * @param validFrom 开始时间
     * @param validTo 结束时间
     */
    public void setValidPeriodUpdate(LocalDateTime validFrom, LocalDateTime validTo) {
        this.validFrom = validFrom;
        this.validTo = validTo;
        addUpdateField("validFrom");
        addUpdateField("validTo");
    }

    /**
     * 设置快速有效期更新
     * @param days 天数
     */
    public void setQuickValidPeriodUpdate(int days) {
        this.validDays = days;
        addUpdateField("validFrom");
        addUpdateField("validTo");
    }

    /**
     * 设置延长有效期
     * @param days 延长天数
     */
    public void setExtendValidPeriod(int days) {
        this.extendDays = days;
        this.operationType = "extend";
        addUpdateField("validTo");
    }

    /**
     * 设置备注更新
     * @param remark 备注
     */
    public void setRemarkUpdate(String remark) {
        this.remark = remark;
        addUpdateField("remark");
    }

    /**
     * 设置分配信息更新
     * @param assignBy 分配人ID
     * @param assignByName 分配人姓名
     */
    public void setAssignInfoUpdate(Long assignBy, String assignByName) {
        this.assignBy = assignBy;
        this.assignByName = assignByName;
        addUpdateField("assignBy");
        addUpdateField("assignByName");
        addUpdateField("assignTime");
    }

    /**
     * 启用通知
     * @param method 通知方式
     */
    public void enableNotification(String method) {
        this.sendNotification = true;
        this.notificationMethod = method;
    }

    /**
     * 禁用通知
     */
    public void disableNotification() {
        this.sendNotification = false;
        this.notificationMethod = null;
    }

    /**
     * 校验通知方式
     * @return 校验结果
     */
    public boolean isNotificationMethodValid() {
        if (!shouldSendNotification()) {
            return true;
        }
        
        String method = notificationMethod.toLowerCase();
        return "email".equals(method) || "sms".equals(method) || "system".equals(method);
    }

    /**
     * 设置永久有效
     */
    public void setPermanentValid() {
        this.validFrom = null;
        this.validTo = null;
        this.validDays = null;
        addUpdateField("validFrom");
        addUpdateField("validTo");
    }

    /**
     * 设置立即过期
     */
    public void setImmediateExpire() {
        this.validTo = LocalDateTime.now();
        this.operationType = "expire";
        addUpdateField("validTo");
    }

    /**
     * 启用关联
     */
    public void enableAssociation() {
        this.status = true;
        this.operationType = "enable";
        addUpdateField("status");
    }

    /**
     * 禁用关联
     */
    public void disableAssociation() {
        this.status = false;
        this.operationType = "disable";
        addUpdateField("status");
    }

    /**
     * 刷新关联（重置有效期）
     */
    public void refreshAssociation() {
        this.operationType = "refresh";
        addUpdateField("validFrom");
        addUpdateField("validTo");
        addUpdateField("assignTime");
    }

    /**
     * 重置关联（恢复默认设置）
     */
    public void resetAssociation() {
        this.operationType = "reset";
        this.status = true;
        this.validFrom = null;
        this.validTo = null;
        this.remark = null;
        addUpdateField("status");
        addUpdateField("validFrom");
        addUpdateField("validTo");
        addUpdateField("remark");
    }

    /**
     * 获取更新描述
     * @return 更新描述
     */
    public String getUpdateDescription() {
        if (operationType != null) {
            switch (operationType.toLowerCase()) {
                case "enable":
                    return "启用关联";
                case "disable":
                    return "禁用关联";
                case "extend":
                    return "延长有效期";
                case "expire":
                    return "设置过期";
                case "refresh":
                    return "刷新关联";
                case "reset":
                    return "重置关联";
                default:
                    return "更新关联";
            }
        }
        
        if (isBatchUpdate()) {
            return "批量更新关联";
        }
        
        return "更新关联";
    }

    /**
     * 获取更新字段数量
     * @return 更新字段数量
     */
    public int getUpdateFieldCount() {
        return updateFields != null ? updateFields.size() : 0;
    }

    /**
     * 检查是否有实际更新内容
     * @return 是否有更新内容
     */
    public boolean hasUpdateContent() {
        return (updateFields != null && !updateFields.isEmpty()) ||
               operationType != null ||
               status != null ||
               validFrom != null ||
               validTo != null ||
               validDays != null ||
               extendDays != null ||
               remark != null ||
               assignBy != null ||
               assignByName != null;
    }

    /**
     * 清空更新字段
     */
    public void clearUpdateFields() {
        if (updateFields != null) {
            updateFields.clear();
        }
    }

    /**
     * 转换为字符串表示
     * @return 字符串表示
     */
    @Override
    public String toString() {
        return "UserRoleUpdateDTO{" +
                "id=" + id +
                ", userId=" + userId +
                ", roleId=" + roleId +
                ", status=" + status +
                ", validFrom=" + validFrom +
                ", validTo=" + validTo +
                ", operationType='" + operationType + '\'' +
                ", updateFields=" + updateFields +
                ", version=" + version +
                '}';
    }
}